
#include <assert.h>
#include <gfx/gl20/shader_gl20.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

namespace
{
GLenum convert_shader_type (ceShaderType type)
{
  switch (type)
  {
  case ST_Vertex:
    return GL_VERTEX_SHADER;

  case ST_Fragment:
    return GL_FRAGMENT_SHADER;

  default:
    assert (false);
  }

  // just keep the compiler calm
  return 0;
}
}

ceShaderGL20::ceShaderGL20 (ceShaderType type)
  : _name (0)
  , _type (type)
  , _compiled (false)
{
  CE_OBJECT_CONSTR;

  _st = convert_shader_type(type);
  CreateShader();
}

void ceShaderGL20::CreateShader()
{
  if (_name)
    {
      glDeleteShader (_name);
    }

  _name = glCreateShader (_st);
  _compiled = false;
}

GLuint ceShaderGL20::GetName () const
{
  return _name;
}

ceShaderType ceShaderGL20::GetShaderType () const
{
  return _type;
}


void ceShaderGL20::SetSource (const std::string& source)
{
  assert (_name != 0);

  const GLchar* str = static_cast<const GLchar*>(source.c_str ());
  const GLint length = (GLuint)source.length ();
  glShaderSource (_name, 1, (const GLchar**)&str, &length);
  _compiled = false;
}


bool ceShaderGL20::Compile ()
{
  assert (_name != 0);
  glCompileShader (_name);
  GLint compileState;
  glGetShaderiv (_name, GL_COMPILE_STATUS, &compileState);
  _compiled = (compileState == GL_TRUE);
  return _compiled;
}

bool ceShaderGL20::IsCompiled() const
{
  return _compiled;
}

std::string ceShaderGL20::GetCompileInfoLog () const
{
  assert (_name != 0);
  static char infoLog[1024];
  GLsizei size;
  glGetShaderInfoLog(_name, 1024, &size, (GLchar*)infoLog);
  infoLog[size] = '\0';
  return std::string(infoLog);
}
